export function getMediaDevices() {
  // 注意本例需要在HTTPS协议网站中运行，新版本Chrome中getUserMedia接口在http下不再支持。
  // 老的浏览器可能根本没有实现 mediaDevices，所以我们可以先设置一个空的对象
  if (navigator.mediaDevices === undefined) {
    navigator.mediaDevices = {};
  }
  // 一些浏览器部分支持 mediaDevices。我们不能直接给对象设置 getUserMedia
  // 因为这样可能会覆盖已有的属性。这里我们只会在没有getUserMedia属性的时候添加它。
  if (navigator.mediaDevices.getUserMedia === undefined) {
    navigator.mediaDevices.getUserMedia = function (constraints) {
      // 首先，如果有getUserMedia的话，就获得它
      const getUserMedia = navigator.getUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
      // 一些浏览器根本没实现它 - 那么就返回一个error到promise的reject来保持一个统一的接口
      if (!getUserMedia) {
        return Promise.reject(new Error('getUserMedia is invalid; confirm https is enabled'));
      }
      // 否则，为老的navigator.getUserMedia方法包裹一个Promise
      return new Promise(function (resolve, reject) {
        getUserMedia.call(navigator, constraints, resolve, reject);
      });
    };
  }
  return navigator.mediaDevices;
}

export default class UserMedia {
  constructor(video) {
    this.video = video;
  }
  stopVideo() {
    const { video } = this;
    video.pause();
    if (video.src) video.src = null;
    if (video.srcObject) video.srcObject = null;
  }
  openVideo() {
    const { video } = this;
    const playVideo = function () {
      video.play();
      window.removeEventListener('click', playVideo, false);
      console.log('video is playing and the listener has removed');
    };
    window.addEventListener('click', playVideo, false);
    video.onloadedmetadata = playVideo;
    // 旧的浏览器可能没有srcObject
    if ('srcObject' in video) {
      video.srcObject = this.stream;
    } else {
      video.src = window.URL.createObjectURL(this.stream);
    }
  }
  async open(option = {}) {
    option = (typeof option === 'object' && option) || {};
    const { video } = this;
    // console.log("screenSize: ", screenSize);
    const opt = {
      audio: false,
      video: {
        width: video.width,
        height: video.height,
      },
    };
    let facingMode;
    /*
     * 前置摄像头：facingMode: "user"，后置摄像头：facingMode: { exact: "environment" }
     * 只有当传入front这个参数时才会尝试去加入约束条件
     */
    if (option.front === true) {
      facingMode = 'user';
      delete option.front;
    } else if (option.front === false) {
      facingMode = { exact: 'environment' };
      delete option.front;
    }

    const mediaDevices = getMediaDevices();

    try {
      const constraints = Object.assign(opt, option, {
        video: Object.assign({ facingMode }, opt.video, option.video),
      });
      this.stream = await mediaDevices.getUserMedia(constraints).catch((error) => {
        throw error;
      });
    } catch (e) {
      const constraints = Object.assign(opt, option, {
        video: Object.assign({}, opt.video, option.video, { facingMode: undefined }),
      });
      this.stream = await mediaDevices.getUserMedia(constraints).catch((error) => {
        throw error;
      });
    }

    this.openVideo();
  }
  close() {
    this.stopVideo();
    if (this.stream) {
      this.stream.getTracks().forEach((track) => track.stop());
    }
  }
  dispose() {
    this.stopVideo();
    this.close();
    this.video = null;
    this.stream = null;
  }
}
